P06-1. 실제 Linux VM 하이브리드 서비스 메시 - 이론 개념
Part 06 (이론): 실제 Linux VM 하이브리드 서비스 메시 (WorkloadGroup · WorkloadEntry · ServiceEntry)
- 실제 엔터프라이즈 인프라(KT Cloud, NCP, AWS, 금융/공공 온프레미스)에서 왜 "모든 서버가 쿠버네티스 파드 안에만 존재하는 순수 K8s 환경" 이 불가능한지(DB VM, 레거시 서버 공존) 이해한다.
- 쿠버네티스 바깥에 떠 있는 실제 Linux VM을 쿠버네티스 안의 파드와 똑같은 '1등 시민(First-Class Citizen)'으로 편입시키는 3대 하이브리드 리소스(
WorkloadGroup,WorkloadEntry,ServiceEntry)의 관계를 쿠버네티스 기본 리소스(Deployment,Pod,Service)와 1:1로 매핑해 설명할 수 있다. - 쿠버네티스
CoreDNS가 모르는 사설 도메인(pg-vm.mesh.internal)을 파드가 어떻게 찾아내는지, Part 03에서 목격했던ztunnel내장 DNS 프록시(127.0.0.1:15053) 와 가상 IP(240.240.0.50)의 원리로 해부한다. - 외부 Linux VM에 에이전트를 설치하지 못하는 관리형 DB(RDS/Cloud DB) 환경(Agentless VM 통합)과, VM 내부에 직접 프록시를 설치하는 환경(Full Agent VM 통합)의 설계 차이를 구분한다.
1. 왜 실무 아키텍처에서는 '쿠버네티스 + 외부 Linux VM' 하이브리드가 필수일까?
교과서나 간단한 튜토리얼에서는 웹 서버도 파드, API 서버도 파드, 심지어 데이터베이스(DB)까지 전부 쿠버네티스 클러스터 안의 파드로만 띄웁니다.
하지만 실제 기업의 프로덕션 인프라를 설계하고 구축해 보면 현실은 전혀 다릅니다.
- 핵심 데이터베이스(PostgreSQL, Oracle 등)의 VM/베어메탈 분리 운영:
데이터 유실이 절대 일어나면 안 되는 메인 DB나 대용량 디스크 I/O가 필요한 PostgreSQL 서버는 쿠버네티스 파드가 아니라, 같은 VPC(또는 피어링된 서브넷)에 있는 별도의 전용 Linux VM이나 클라우드 관리형 DB(AWS RDS, NCP Cloud DB, KT Cloud DB) 위에 구축하는 경우가 압도적으로 많습니다. - 점진적 차세대 전환 (Legacy Coexistence):
수년간 잘 돌아가던 수십 대의 Linux VM 기반 결제/정산 시스템을 하루아침에 전부 컨테이너로 바꿀 수는 없습니다. K8s로 먼저 옮긴 신규 서비스들과 기존 Linux VM들이 최소 몇 년 동안은 끊임없이 통신해야 합니다.
하이브리드 메시가 없을 때 벌어지는 문제점
만약 쿠버네티스 파드가 클러스터 바깥의 PostgreSQL VM(172.19.0.7:5432)을 그냥 IP 주소로 직접 호출하면 어떤 문제가 생길까요?
- 메시 장부에서의 실종 (Blind Spot):
ztunnel과Waypoint입장에서는172.19.0.7이 우리 회사의 소중한 DB 서버인지, 해커의 외부 C&C 서버인지 전혀 구분할 수 없습니다. 나중에 Kiali나 Grafana로 서비스 지도를 그려도 просто'PassthroughCluster'(정체불명의 외부 트래픽)로 뭉뚱그려져 보입니다. - Zero-Trust 보안 적용 불가: "오직
order-api파드만 외부 PostgreSQL VM의5432포트에 접속할 수 있고, 클러스터 안의 다른 파드(rogue-client)는 DB VM에 절대 접속하지 못하게 막아라!" 같은 IstioAuthorizationPolicy를 걸 수 없습니다. - IP 하드코딩과 장애 조치(Failover)의 어려움: DB VM이 죽어서 대기 중이던 예비 VM(
172.19.0.8)으로 절체될 때 애플리케이션 설정을 일일이 고쳐야 합니다.
이 문제를 해결하기 위해 Istio는 "몸체는 쿠버네티스 바깥(Linux VM)에 있지만, 서비스 메시 장부에는 쿠버네티스 파드와 똑같은 정식 가족(명예 파드)으로 호적을 올려주는" 하이브리드 기능을 제공합니다!
2. 쿠버네티스 리소스 vs Istio 하이브리드 VM 리소스 1:1 비교
초보자가 WorkloadGroup, WorkloadEntry, ServiceEntry라는 세 가지 단어를 처음 들으면 외계어처럼 느껴집니다.
하지만 우리가 이미 잘 알고 있는 쿠버네티스의 Deployment · Pod · Service 와 나란히 놓고 비교하면 단 1분 만에 이해됩니다!
flowchart TB
subgraph K8S_WORLD["쿠버네티스 내부 세계 (컨테이너용)"]
direction LR
D["Deployment
(파드 생성 틀 & 공통 설정)"] --> P["Pod
(실제 컨테이너 1개 + IP + 라벨)"]
P --> S["Service
(라벨 셀렉터로 파드들을 묶고
고정 도메인 & VIP 부여)"]
end
subgraph VM_WORLD["Istio 하이브리드 세계 (외부 Linux VM용)"]
direction LR
WG["WorkloadGroup
(VM 그룹의 공통 템플릿:
ServiceAccount, 라벨, 네트워크)"] --> WE["WorkloadEntry
(실제 외부 VM 1대의 주민등록증:
VM IP 172.19.0.7 + 라벨)"]
WE --> SE["ServiceEntry (또는 K8s Service!)
(라벨 셀렉터로 WorkloadEntry를 묶고
pg-vm.mesh.internal 도메인 부여)"]
end
WorkloadGroup(워크로드 그룹 = VM용Deployment):- 같은 역할을 하는 외부 Linux VM 무리(예: PostgreSQL DB 클러스터 VM들)가 공통으로 가질 라벨(
app: external-pg-vm), 서비스 계정(serviceAccount: default), 소속 네트워크 이름 등을 정의해 놓는 '틀(Template)'입니다.
- 같은 역할을 하는 외부 Linux VM 무리(예: PostgreSQL DB 클러스터 VM들)가 공통으로 가질 라벨(
WorkloadEntry(워크로드 엔트리 = VM용Pod주민등록증):- 쿠버네티스 바깥에 떠 있는 실제 Linux VM 딱 1대를 가리키는 리소스입니다!
- 이 안에 그 VM의 실제 IP 주소(
address: 172.19.0.7) 와 라벨(labels: {app: external-pg-vm}) 을 적어 두면, Istio(istiod)는 이 외부 VM을 마치 쿠버네티스 안에 떠 있는 진짜 파드(Endpoint)처럼 취급하기 시작합니다!
ServiceEntry(서비스 엔트리 = 메시의 외부/커스텀 전화번호부):- 쿠버네티스 기본 DNS(
*.svc.cluster.local)에 없는 새로운 도메인 이름(예:pg-vm.mesh.internal) 과 가상 IP(240.240.0.50), 포트(5432 / TCP) 를 서비스 메시 전체의 공식 전화번호부에 등록하는 리소스입니다. - 특히
ServiceEntry안에workloadSelector: {labels: {app: external-pg-vm}}를 적어 주면, 방금 등록한WorkloadEntry(외부 VM들)를 자동으로 찾아내어 그 도메인의 백엔드 서버(EDS)로 묶어 줍니다!
- 쿠버네티스 기본 DNS(
놀라운 보너스: 일반 쿠버네티스 Service도 WorkloadEntry(외부 VM)를 자동으로 묶어 줍니다!
더욱 놀라운 사실이 하나 있습니다.
우리가 평소에 파드들을 묶을 때 쓰던 가장 평범한 쿠버네티스 kind: Service (name: external-pg)를 만들고, 그 안에 selector: {app: external-pg-vm} 이라고 적으면 어떻게 될까요?
쿠버네티스 안에는 app: external-pg-vm 라벨을 가진 파드가 0개지만, Istio가 같은 라벨을 가진 WorkloadEntry(172.19.0.7)를 찾아내어 그 쿠버네티스 Service의 엔드포인트로 자동 연결해 줍니다!
즉, 파드들은 외부 VM을 부를 때:
ServiceEntry가 만든 커스텀 도메인(pg-vm.mesh.internal:5432)으로 불러도 되고,- 쿠버네티스 표준 서비스 도메인(
external-pg.part1-demo.svc.cluster.local:5432)으로 불러도 똑같이 외부 Linux VM으로 연결됩니다!
3. 커널 내부의 비밀: CoreDNS가 모르는 pg-vm.mesh.internal 주소를 누가 알려줬을까?
여기서 아주 중요한 질문이 생깁니다.
"쿠버네티스의 기본 DNS 서버인 CoreDNS는 .cluster.local로 끝나는 쿠버네티스 서비스 이름만 알고 있잖아요. 우리가 방금 지어낸 pg-vm.mesh.internal이라는 도메인은 CoreDNS에 등록한 적도 없는데, 파드 안에서 psql -h pg-vm.mesh.internal을 치면 어떻게 에러가 안 나고 240.240.0.50이라는 IP를 찾아내나요?"
정답은 Part 03 실습의 Step 3에서 우리가 nsenter로 파드 방 안을 들여다봤을 때 발견했던 127.0.0.1:15053 소켓(ztunnel 내장 DNS 프록시) 에 있습니다!
sequenceDiagram
autonumber
participant Pod as pg-client 파드
(K8s 내부)
participant DNS as ztunnel 내장 DNS 서버
(파드 내부 127.0.0.1:15053)
participant ZT as ztunnel L4 프록시
(파드 내부 :15001)
participant WP as Waypoint Proxy
(메시 L7/L4 관문)
participant VM as study-pg-vm
(외부 Linux VM · 172.19.0.7:5432)
Pod->>DNS: 1. DNS 질의: "pg-vm.mesh.internal의 IP가 뭐야?"
Note over DNS: CoreDNS까지 가지도 않음!
istiod에게 받은 ServiceEntry 장부 확인 후 즉시 응답!
DNS-->>Pod: 2. DNS 응답: "가상 IP 240.240.0.50 이야!"
Pod->>ZT: 3. TCP 연결 시도 (240.240.0.50:5432) -> :15001에서 납치!
ZT->>WP: 4. HBONE (:15008) mTLS 터널로 Waypoint에 전달
(dst.hbone_addr = 240.240.0.50:5432)
Note over WP: 5. 인가 정책(AuthorizationPolicy) 심사 후
WorkloadEntry의 실제 VM IP(172.19.0.7:5432)로 변환!
WP->>VM: 6. 실제 외부 PostgreSQL 18 VM(172.19.0.7:5432)으로 패킷 전달 및 SQL 실행!- 파드 내부 DNS 가로채기 (
127.0.0.1:15053): Ambient Mesh에 편입된 파드가 도메인 주소를 물어보면(UDP/TCP 53번 포트), 파드 네트워크 방(NetNS)의iptables규칙이 그 질의를 낚아채어 파드 방 안에 열려 있는ztunnel의 내장 DNS 서버(127.0.0.1:15053) 로 보냅니다. ServiceEntry가상 IP 즉시 응답:ztunnel은 이미istiod로부터 모든ServiceEntry목록을 받아 알고 있으므로,CoreDNS에게 물어볼 필요도 없이 0.1ms 만에 "pg-vm.mesh.internal의 주소는240.240.0.50이야!" 라고 대답해 줍니다.- (참고:
240.240.0.0/16대역은 인터넷에서 쓰이지 않는 예약 대역인 Class E 주소로, Istio가 외부/커스텀 서비스를 식별하기 위해 내부적으로 부여하는 가짜 대표 번호입니다.)
- (참고:
HBONE터널링 및 실제 VM IP(172.19.0.7) 라우팅: 파드가240.240.0.50:5432로 패킷을 쏘면ztunnel이 이를 잡아HBONE(:15008)터널에 실어Waypoint Proxy로 보내고,Waypoint는 그 대표 번호에 연결된WorkloadEntry의 실제 VM IP(172.19.0.7:5432)로 정확히 패킷을 배달합니다!
4. 실무 아키텍처 팁: 외부 VM을 메시에 연결하는 2가지 방식 비교
현업에서 외부 VM을 Istio 메시에 통합할 때는 내가 그 VM 내부에 루트(root) 권한으로 프로그램을 설치할 수 있는가? 에 따라 두 가지 방식 중 하나를 선택합니다.
| 비교 항목 | 방식 A · Agentless 하이브리드 연동 (본 실습 방식) | 방식 B · VM 내부 에이전트 설치 연동 (istio-sidecar.rpm/deb) |
|---|---|---|
| VM 내부 설치 여부 | 설치 불필요! (순수 PostgreSQL이나 레거시 앱만 그대로 돌아감) | Linux VM 내부에 직접 istio-sidecar 데몬(envoy + pilot-agent) 설치 필요 |
| 적용 가능한 환경 | AWS RDS, KT Cloud DB, NCP Cloud DB 등 관리형 DB 및 에이전트 설치가 금지된 레거시/벤더 서버까지 100% 적용 가능! | OS 루트 권한을 직접 가진 자체 구축 Linux VM |
| 보안 및 암호화 구간 | K8s 파드 ↔ ztunnel ↔ Waypoint Proxy 구간까지 HBONE mTLS 및 RBAC 통제 적용, Waypoint → 외부 VM 구간은 VPC 내부 네트워크 통신 |
K8s 파드부터 외부 VM 내부의 Envoy까지 전 구간 End-to-End mTLS 적용 |
| 운영 복잡도 | 매우 낮음 (쿠버네티스 YAML 3개만 등록하면 즉시 완료!) | 높음 (VM용 부트스트랩 토큰 발급, 방화벽 오픈, 에이전트 데몬 관리 필요) |
WorkloadEntry + ServiceEntry + Waypoint)를 먼저 도입하나요?
기업에서 가장 흔한 하이브리드 대상은 클라우드 사업자가 관리하는 DB(RDS / Cloud DB) 이거나, 손대면 안 되는 오래된 DB VM입니다. 이러한 서버에는 애초에 SSH 접속이나 외부 데몬 설치가 불가능합니다.
반면 방식 A를 사용하면 외부 DB VM은 손끝 하나 건드리지 않고도, 쿠버네티스 안에서 DB로 나가는 모든 트래픽을 Waypoint Proxy 에 집중시켜 누가 DB에 접속할 수 있는지(AuthorizationPolicy), 연결 수를 몇 개로 제한할지(Circuit Breaker), DB 연결 지연이 얼마인지(LGTM 메트릭/로그) 를 100% 통제하고 관측할 수 있습니다!
🔗 다음 단계 (실습 검증)
이론으로 배운 3세대 하이브리드 서비스 메시를 이제 직접 검증해 봅니다!
- 쿠버네티스 클러스터 바깥의 Docker
kind브릿지 네트워크(172.19.0.0/16)에 실제 PostgreSQL 18 Linux VM 컨테이너(study-pg-vm) 를 띄우고, WorkloadGroup·WorkloadEntry·ServiceEntry로 이 외부 VM을 메시에 등록한 뒤,- 쿠버네티스 내부의
pg-client파드에서pg-vm.mesh.internal도메인으로 접속해 실제 SQL(CREATE TABLE,INSERT,SELECT)을 실행하고, - 침입자 파드(
rogue-client)가 외부 DB VM에 접속하려 할 때 메시가 DB 앞단에서 차단하는 하이브리드 보안까지 완벽히 실습합니다!
네비게이션
| 이전 | 목록 | 다음 |
|---|---|---|
| ◀ Part 05 실습 | 목록으로 | Part 06 실습 ▶ |